Skip to content

feat: lumped loads, phased feeders, and four reworked antenna models#65

Merged
EA1FUO merged 11 commits into
mainfrom
feat/antenna-template-extensions
May 30, 2026
Merged

feat: lumped loads, phased feeders, and four reworked antenna models#65
EA1FUO merged 11 commits into
mainfrom
feat/antenna-template-extensions

Conversation

@EA1FUO

@EA1FUO EA1FUO commented May 30, 2026

Copy link
Copy Markdown
Owner

Extends the antenna template system to model antennas that need lumped loads, transmission-line feeders, or phased feeds — then reworks four templates that were structurally broken without those capabilities. Every antenna is
validated end-to-end against nec2c. Releases v1.2.0.

Foundation

  • AntennaTemplate.generateExcitation may now return an array (multiple/phased feeds), plus optional generateLoads and generateTransmissionLines hooks.
  • The Simulator now dispatches through the unified advanced engine path (which already supported loads/TLs/multi-excitation). Existing single-excitation templates are untouched — verified to produce identical results.

Antenna fixes

  • Magnetic Loop — never resonated (no tuning capacitor, fed directly). Now a closed main loop with a series tuning capacitor (from the loop inductance) plus a fed Faraday coupling loop, with two new controls: Coupling Loop Size
    (sets feed resistance) and Capacitor Tuning (peaks resonance). nec2c: SWR ~500 → ~1.4.
  • G5RV — modeled the 450 Ω open-wire feeder as a radiating wire (~99:1). Now a transmission line (velocity-factor-corrected length) to a coax stub. nec2c: ~1.9:1 on 20 m, realistic tuner-needed behavior elsewhere.
  • Log-Periodic (LPDA) — only fed the front element, leaving the rest as floating parasitics. Now a proper transposed phase line: Carrel-designed feeder Z₀, crossed (negative-Z₀) TLs between element centers, a shorted rear
    termination stub, and an element range extended past both band edges. nec2c: ~11 dBi forward gain, SWR mostly <2 across 14–30 MHz.

Viewport

  • Transmission-line feeders (and other non-radiating structures) now render as dashed lines in both the Simulator and Wire Editor, so TL-fed antennas no longer show a feedpoint floating disconnected from the antenna.

Backend

  • Relaxed the transmission-line impedance constraint to allow a negative characteristic impedance — NEC's convention for a crossed/transposed line (magnitude still bounded). Required for the LPDA phase line.

Release

  • Version bump to 1.2.0 (VERSION, package.json, package-lock.json, pyproject.toml, README badge); CHANGELOG [1.2.0] section covers this release.

Testing

  • tsc --noEmit, eslint (0 errors), vitest (315 tests), vite build all pass.
  • Every antenna validated end-to-end against the backend with nec2c.

▎ Note: this PR touches the backend (antenna.py), so it exercises both services — after merge, the backend must include this change for the LPDA's transposed feeder.

EA1FUO added 11 commits May 29, 2026 15:38
…ions

The driven element and reflector were ~2.8x too wide (~1.04 wavelength
instead of ~0.37), which detuned the antenna and produced SWR >99 across
the entire band.

Two compounding errors in moxonDimensions():
- The polynomial coefficients did not match the standard Cebik/MoxGen
  Moxon equations.
- The full element width A was treated as a half-width and then doubled.

Replaced the formulas with L.B. Cebik's (W4RNL) MoxGen regression
equations and corrected the full-width vs. half-width handling. The
14.15 MHz / 2 mm design now comes out to 7.73 m x 2.81 m, matching MoxGen.

Closes #63
The End-Fed Half-Wave geometry fixed the horizontal span at the
half-wave length and set the far-end height independently, so the actual
conductor was the hypotenuse — longer than a half-wave whenever the ends
were at different heights. With the default 40m design (feed 10 m, far
end 3 m) the wire came out 21.66 m instead of 20.49 m (~5.7% long),
pushing resonance below the swept band and leaving SWR ~3.9 at the
design frequency.

The horizontal run is now derived from the height drop so the conductor
is always a true half-wave; changing the far-end height tilts the sloper
instead of stretching the wire. A clamp keeps the geometry valid if the
requested height drop exceeds the wire length. Verified with nec2c
(average ground, 49:1 transform): SWR at the 7.1 MHz design point drops
from 3.88 to 1.49, with resonance landing near the design frequency.
The fan dipole only matched on its lowest band; 20m and 10m showed very
high SWR. Three compounding problems:

1. Feed topology: every element's left and right halves all terminated
   at one common node, with the source on the longest element's segment.
   Only that dipole straddled the source across its center and was driven
   differentially; the other elements had both halves tied to the same
   node, so they were never excited as dipoles and hung off the feed as
   quasi-parasitic stubs (high, reactive impedance -> very high SWR).
2. Fan spread stretched each element: the horizontal span was fixed at
   the half-length while the ends dropped vertically, so the conductor
   was longer than its resonant length (worse on higher bands).
3. End-effect shortening put the coupled elements above their bands.

Now all left halves join a left terminal and all right halves a right
terminal, bridged by a short driven feed segment, so every dipole is fed
across its center simultaneously. Each arm is held at a fixed length and
the fan spread only tilts it. Element length compensates for the upward
resonance shift caused by fan mutual coupling.

Verified with nec2c (average ground, default 40/20/10m design): in-band
SWR at band centers improves from ~1.8/14/27 to ~2.7/2.3/1.9 for
40m/20m/10m. Fan dipoles still benefit from per-element trimming in
practice, but all bands are now usable out of the box.
The AntennaTemplate interface only allowed a single excitation and no
lumped loads, so antennas that need a tuning capacitor (magnetic loop),
a phased feeder (log-periodic), or a transmission-line feeder (G5RV)
could not be modelled correctly in the simulator.

Extend the interface:
- generateExcitation may now return Excitation | Excitation[]
- add optional generateLoads() and generateTransmissionLines()

The downstream advanced engine path (simulateAdvanced) already supports
excitation arrays, loads and transmission lines end to end, so the
simulator now dispatches through it instead of the single-excitation V1
path. antennaStore normalises the excitation to an array and invokes the
optional load/TL generators; the editor's Load Template carries them
over too.

Existing single-excitation templates are untouched (the union keeps a
bare Excitation valid). Verified against the backend (nec2c) that a
dipole returns identical results through the new path: min SWR 1.424 @
14.473 MHz, Z 71.0-2.6j, gain 7.2.
The Small Magnetic Loop never resonated: it had no tuning capacitor (so
the electrically tiny loop was a pure inductive reactance) and was fed
directly (a resonant small loop is well under 1 ohm, so even resonant it
would be a near-total mismatch). SWR pegged near infinity across the band.

Model it the way a real small transmitting loop works, using the new
template load capability:
- a closed main loop carrying a series tuning capacitor at the top,
  with C computed from the loop inductance (mu0*a*(ln(8a/b)-2)) and an
  empirical correction calibrated against nec2c so it resonates on
  frequency;
- a small fed Faraday coupling loop near the bottom that transforms the
  loop's sub-ohm radiation resistance up to ~50 ohms.

Each arc segment is its own unique-tag wire so the feed and capacitor
can address a specific point (the backend validates excitation segments
per wire). Two new controls mirror real loop tuning: Coupling Loop Size
sets the feed resistance, Capacitor Tuning peaks resonance. The default
frequency sweep is tightened because the loop is only a few kHz wide.

Verified end to end against the backend (nec2c): SWR ~500 -> ~1.4 at
resonance for the default design, and the recipe generalises across loop
sizes and bands. Also fixed the feedpoint marker, which used Three.js
coordinates instead of the NEC coordinates the viewport expects.
The 450-ohm matching section was modelled as a single vertical wire,
which radiates and presents a common-mode impedance unlike a balanced
line, so the default G5RV showed ~99:1 SWR. Model it instead as a NEC
transmission line between the dipole center and a short coax stub, with
the line length scaled by the 0.91 velocity factor of 450-ohm window
line (NEC's TL is ideal, VF=1). Verified with nec2c: ~1.9:1 on 20m (the
G5RV's design band), with realistic tuner-needed behaviour on the other
bands.
Transmission lines are non-radiating (ideal 2-port) elements, so they
were not drawn at all — leaving the feedpoint of a TL-fed antenna (e.g.
the G5RV) floating disconnected from the antenna. Add a reusable
NonRadiatingLines component plus a resolver that turns TL port references
into 3D segments, and render them dashed in both the Simulator
(SceneRoot) and Wire Editor (EditorScene) viewports.
The LPDA fed only the front element and left the rest as floating
parasitics, so it produced no real log-periodic behaviour. Model the
proper phase-line feeder using the new template transmission-line
capability:
- a Carrel-designed feeder characteristic impedance derived from tau,
  sigma, the element impedance and the 50-ohm target;
- crossed (transposed) transmission lines between adjacent element
  centers, giving the 180-degree alternation (negative NEC Z0);
- a shorted rear termination stub behind the longest element;
- an element range extended past both band edges so the active region
  never runs off the front element.

The backend rejected negative transmission-line impedance, but that is
NEC's convention for a crossed/transposed line, so the constraint is
relaxed to allow it (magnitude still bounded).

Verified end to end against the backend (nec2c): ~11 dBi forward gain
and SWR mostly under 2 across the full 14-30 MHz design range.
…efs valid

Two issues made the G5RV/LPDA feeder dashed line render off-vertical:

1. The Wire Editor re-segments wires when the design frequency changes,
   scaling excitation segments but not transmission-line or lumped-load
   segment references. A loaded G5RV's feeder then pointed at segment 21
   of a re-segmented 9-segment wire, so the viewport extrapolated past
   the wire end (~52deg) and the line was also invalid for simulation.
   setDesignFrequency now scales TL and load segments the same way, and
   the viewport defensively clamps a stale reference onto the wire.

2. The G5RV fed the transmission line from the last segment of a dipole
   arm, whose center sits half a segment short of the true dipole center
   (~5deg with coarse segmentation). Model the dipole as a single wire
   fed at its center segment instead (autoSegment returns odd counts, so
   the center segment is the exact midpoint). Verified with nec2c that
   this is electrically identical to the two-arm version (1.85 vs 1.86
   on 20m). The feeder now renders perfectly vertical in both views.
@EA1FUO EA1FUO merged commit c9788df into main May 30, 2026
2 checks passed
@EA1FUO EA1FUO deleted the feat/antenna-template-extensions branch May 30, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant